package medOffice;

import java.sql.SQLException;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import medOffice.Enuns.Sexo;
import medOffice.Enuns.TipoDeConsulta;
import medOffice.Enuns.Urgencia;
import medOffice.dao.tests.ConsultaDAOTest;
import medOffice.dao.tests.MedicoDAOTest;
import medOffice.dao.tests.PacienteDAOTest;
import medOffice.dao.tests.PlanoDAOTest;
import medOffice.dao.tests.RepresentanteDAOTest;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * Testes da Classe Agenda
 * 
 * @author Ana Clara Lacerda - anacls@lcc.ufcg.edu.br
 * @version 0.2 - 08/11/2009
 */
public class AgendaTest {

	Medico med1, med2;
	Agenda a1, a2;
	Paciente p1, p2, p3;
	Clinica clinica;
	PlanoDeSaude plano1, plano2;
	
	class MinhaAgenda extends Agenda{

		public MinhaAgenda(Medico medico) throws Exception {
			super(medico);
			super.consultaDAO = new ConsultaDAOTest();
		}
		
	}
	class MinhaClinica extends Clinica{
		public MinhaClinica(String nome) throws Exception {
			super(nome);
			daoRepresentante = new RepresentanteDAOTest();
			daoPaciente = new PacienteDAOTest();
			daoMedico = new MedicoDAOTest();
			daoPlano = new PlanoDAOTest();
		}
	}
	

	@Before
	public void setUp() throws Exception{
		GerarBDTest.main(null);
		
		
		
		clinica = new MinhaClinica("Sta Maria");
		
		clinica.setEndereco("Rua Copacabana");
		clinica.setTelefone("(83) 3355-1593");
		
		med1 = new Medico("Jenesio", "000000000-12");
		med1.adicionaHorarioDisponivel(3, new Time[] {
				Time.valueOf("12:00:00"), Time.valueOf("16:00:00") });
		med1.adicionaPlanoDeSaude(new PlanoDeSaude("Unimed", "(83) 3222-2222",
				200, 100, 1));
		
		med1.setTempoConsulta("00:30:00");
		med1.setTempoRetorno("00:20:00");
		
		med1.setDataDeNascimento(new GregorianCalendar(1990,1,10));
		med1.setSexo(Sexo.M);
		
		try{
			clinica.addMedico(med1);
		}catch(Exception ex){
			
		}

		med2 = new Medico("Junior", "123456789-00");
		med2.adicionaHorarioDisponivel(3, new Time[] {
				Time.valueOf("10:00:00"), Time.valueOf("12:00:00") });
		med2.adicionaPlanoDeSaude(new PlanoDeSaude("Cassi", "(83) 3222-2222",
				200, 100, 2));
		
		med2.setDataDeNascimento(new GregorianCalendar(1990,1,10));
		med2.setSexo(Sexo.M);
				
		
		plano1 = new PlanoDeSaude("Unimed", "(83) 3222-2222", 200, 100, 2);
		plano2 = new PlanoDeSaude("Cassi", "(83) 3222-1591", 200, 100, 20);
		
		clinica.addPlanoDeSaude(plano1);
		clinica.addPlanoDeSaude(plano2);
		
		
		p1 = new Paciente("Ana Clara", "123123123-12", "rua joao pessoa", "(83) 8721-9963", new GregorianCalendar(1987,12,27),"aninhaa136@gmail.com", Sexo.F ,plano1);
		p2 = new Paciente("Tiago Leite","064857574-81", "rua antonio joaquim", "(83) 8865-3972", new GregorianCalendar(1987,12,27),"chalanger@gmail.com", Sexo.M, plano1);
		p3 = new Paciente("Amilton Aciole", "000000000-00", "rua sei la onde", "(83) 8882-9632", new GregorianCalendar(1987,12,27), "amiltonacioli@gmail.com",Sexo.M, plano2);
		
		clinica.addPaciente(p1);
		clinica.addPaciente(p3);
		clinica.addPaciente(p2);

		a1 = new MinhaAgenda(med1);
		clinica.setAgenda(a1);
		a2 = new MinhaAgenda(med2);		
		
	}

	@Test(expected = Exception.class)
	public void construtorMedicoNull() throws Exception{
		new Agenda(null);
	}

	@Test
	public void testaInicializacaoDeObjetos() throws SQLException {
		Assert.assertNotNull(a1.getListaDeConsultas());
		Assert.assertNotNull(a2.getListaDeConsultas());
	}

	@Test
	public void testaGetters() {
		Assert.assertEquals("Erro no dono da agenda 1", med1, a1
				.getDonoAgenda());
		Assert.assertEquals("Erro no dono da agenda 2", med2, a2
				.getDonoAgenda());
	}

	@Test(expected = Exception.class)
	public void marcaConsultaNull() throws Exception {
		a1.marcaConsulta(null);
	}

	@Test
	public void marcaConsultaTest() throws Exception {
		Consulta c = null;
		c = new Consulta(p1,new GregorianCalendar(2008, 06, 9, 15, 30), Urgencia.S);
		Assert.assertFalse("Nao deveria marcar consulta/Ano passado.", a1.marcaConsulta(c));
		c = new Consulta(p1 , new GregorianCalendar(2009, 11, 5, 03, 00), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar consulta/Paciente nulo.", a1.marcaConsulta(c));		
		
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 14, 00, 00), Urgencia.N);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		
		Assert.assertEquals("Erro na lista de consulta", 1, a1.getListaDeConsultas().size());
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 12, 00), Urgencia.N);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 15, 30), Urgencia.S);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 6, 14, 20), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar em dia invalido", a1
				.marcaConsulta(c));
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 18, 20), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar em hora invalida", a1
				.marcaConsulta(c));
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 16, 00), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar em hora final invalida", a1
				.marcaConsulta(c));
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 15, 40), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar em hora final invalida, choque de horario", a1
				.marcaConsulta(c));
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 12, 00), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar em hora final invalida, choque de horario", a1
				.marcaConsulta(c));
		
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 15, 02), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar em hora oculpada", a1
				.marcaConsulta(c));
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 12, 29), Urgencia.N);
		Assert.assertFalse("Nao deveria marcar em hora oculpada", a1
				.marcaConsulta(c));
		c = new Consulta(p1, new GregorianCalendar(2009, 11, 8, 12, 30), Urgencia.N);
		Assert.assertTrue("Deveria marcar a consulta", a1
				.marcaConsulta(c));
		
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), 4);
		
		Assert.assertEquals("Erro na lista de urgencias", a1.listaDeUrgencia().size(), 1);
		
		c = new Consulta(p2, new GregorianCalendar(2009, 11, 15, 14, 00, 00), Urgencia.N);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		c = new Consulta(p2, new GregorianCalendar(2009, 11, 15, 12, 00), Urgencia.N);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		c = new Consulta(p2, new GregorianCalendar(2009, 11, 15, 15, 30), Urgencia.S);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), 7);
		
		Assert.assertEquals("Erro na lista de urgencias", a1.listaDeUrgencia().size(), 2);
	}
	
	@Test(expected = Exception.class)
	public void cancelaConsultaNull() throws Exception{
		a1.cancelaConsulta(null);

	}
	
	@Test
	public void cancelaConsultaTest() throws Exception{
		marcaConsultaTest();
		Consulta c = null;
		c = new Consulta(p1, new GregorianCalendar(2009, 12, 5, 20, 00), Urgencia.N);
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), 7);
		Assert.assertFalse(a1.cancelaConsulta(c));
		int consultas = a1.getListaDeConsultas().size();
		List<Consulta> lista = new ArrayList<Consulta>();
		for (Consulta co : a1.getListaDeConsultas()) {
			lista.add(co);
		}
		for (Consulta co : lista) {
			Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), consultas);
			Assert.assertTrue(a1.cancelaConsulta(co));
			consultas--;
		}
		Assert.assertTrue(a1.getListaDeConsultas().isEmpty());
		Assert.assertTrue(a1.listaDeUrgencia().isEmpty());
	}
	
	@Test(expected = Exception.class)
	public void cancelaConsultaCPFNull() throws Exception{
		a1.cancelaConsultaCPF(null);
	}
	
	@Test
	public void cancelaConsultaCPFTest() throws Exception{
		marcaConsultaTest();
		a1.cancelaConsultaCPF(p1.getCPF());
		a1.cancelaConsultaCPF(p2.getCPF());
		
		Assert.assertTrue(a1.getListaDeConsultas().isEmpty());
		Assert.assertTrue(a1.listaDeUrgencia().isEmpty());
		
		marcaConsultaTest();
		
		a1.cancelaConsultaCPF(p2.getCPF());
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), 4);
		Assert.assertEquals("Erro na lista de urgencias", a1.listaDeUrgencia().size(), 1);
		a1.cancelaConsultaCPF(p1.getCPF());
		
		Assert.assertTrue(a1.getListaDeConsultas().isEmpty());
		Assert.assertTrue(a1.listaDeUrgencia().isEmpty());
		
		marcaConsultaTest();
		
		a1.cancelaConsultaCPF(p1.getCPF());
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), 3);
		Assert.assertEquals("Erro na lista de urgencias", a1.listaDeUrgencia().size(), 1);
		a1.cancelaConsultaCPF(p2.getCPF());
		
		Assert.assertTrue(a1.getListaDeConsultas().isEmpty());
		Assert.assertTrue(a1.listaDeUrgencia().isEmpty());
	}
	
	@Test(expected = Exception.class)
	public void cancelaConsultaDiaNull() throws Exception{
		a1.cancelaConsultaDia(null);
	}
	
	@Test
	public void cancelaConsultaDiaTest() throws Exception{
		marcaConsultaTest();
		a1.cancelaConsultaDia(new GregorianCalendar(2009, 11, 8, 12, 00));
		a1.cancelaConsultaDia(new GregorianCalendar(2009, 11, 15, 12, 30));
		Assert.assertTrue(a1.getListaDeConsultas().isEmpty());
		Assert.assertTrue(a1.listaDeUrgencia().isEmpty());
		
		marcaConsultaTest();
		a1.cancelaConsultaDia(new GregorianCalendar(2009, 11, 8, 12, 00));
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), 3);
		Assert.assertEquals("Erro na lista de urgencias", a1.listaDeUrgencia().size(), 1);
		a1.cancelaConsultaDia(new GregorianCalendar(2009, 11, 15, 12, 30));
		Assert.assertTrue(a1.getListaDeConsultas().isEmpty());
		Assert.assertTrue(a1.listaDeUrgencia().isEmpty());
		
		marcaConsultaTest();
		a1.cancelaConsultaDia(new GregorianCalendar(2009, 11, 15, 12, 00));
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), 4);
		Assert.assertEquals("Erro na lista de urgencias", a1.listaDeUrgencia().size(), 1);
		a1.cancelaConsultaDia(new GregorianCalendar(2009, 11, 8, 12, 30));
		Assert.assertTrue(a1.getListaDeConsultas().isEmpty());
		Assert.assertTrue(a1.listaDeUrgencia().isEmpty());
		
	}
	
	@Test(expected = Exception.class)
	public void listaConsultasDiaNull() throws Exception{
		a1.listaConsultas(null);
	}
	
	@Test(expected = Exception.class)
	public void listaConsultasDiaInvalido() throws Exception {
		Calendar data = new GregorianCalendar(2009, 12, 4);
		a1.listaConsultas(data);
	}
	
	@Test
	public void dicaDiaAgenda() throws Exception{
		marcaConsultaTest();
		int numeroConsultas = a1.getListaDeConsultas().size();
		Calendar dicaAnterior = a1.proximoDiaDisponivel(TipoDeConsulta.CONSULTA);
		Assert.assertEquals("devem ser iguais pois nao houve alteracao na lista",
				dicaAnterior, a1.proximoDiaDisponivel(TipoDeConsulta.CONSULTA));
		
		Consulta c = new Consulta(p1, a1.proximoDiaDisponivel(TipoDeConsulta.CONSULTA), Urgencia.N);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		
		Assert.assertNotSame("Deveria ser diferente", dicaAnterior, 
				a1.proximoDiaDisponivel(TipoDeConsulta.CONSULTA));
		
		dicaAnterior = a1.proximoDiaDisponivel(TipoDeConsulta.RETORNO);
		Assert.assertEquals("devem ser iguais pois nao houve alteracao na lista",
				dicaAnterior, a1.proximoDiaDisponivel(TipoDeConsulta.RETORNO));
		
		c = new Consulta(p1, a1.proximoDiaDisponivel(TipoDeConsulta.RETORNO), 
				Urgencia.N);
		Assert.assertTrue("Deveria marcar a consulta", a1.marcaConsulta(c));
		
		Assert.assertEquals("Erro na lista de consultas", a1.getListaDeConsultas().size(), numeroConsultas+2);
	}
	public void limpaTabelas(Clinica clin) throws SQLException {
		for (int i=0; i < clin.getListaDePlanos().size(); i++) {
			clin.removePlanoDeSaude(clin.getListaDePlanos().get(i));			
		}
		for (int i=0; i < clin.getListaPacientes().size(); i++) {
			clin.removePaciente(clin.getListaPacientes().get(i).getNome(), clin.getListaPacientes().get(i).getCPF());
		}
	}
	
	
	
	
}
